package com.gitee.wsl.android.ui.base

import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
import com.gitee.wsl.android.ui.ext.type.CanvasExt
import com.gitee.wsl.common.ui.api.ContainsPointCheckAble
import com.gitee.wsl.common.ui.api.SizeChangeAble
import com.gitee.wsl.common.ui.base.Padding
import com.gitee.wsl.common.ui.base.plus
import com.gitee.wsl.common.ui.draw.type.LineSpacingStyle
import com.gitee.wsl.common.ui.draw.type.RectType
import com.gitee.wsl.ext.base.ifValue
import com.gitee.wsl.mathematics.geometry.shape.Rectangle
import com.google.android.material.shape.MaterialShapeDrawable

interface Border{
    var borderWidth:Float
    var rectType: RectType
}

open class BorderDrawable(val innerRectangle: Rectangle): ContainsPointCheckAble, MaterialShapeDrawable(),
    SizeChangeAble, Border {
     override var borderWidth :Float
        get() = strokeWidth
        set(value) {
            strokeWidth = value
            linePaint.strokeWidth = value
        }

    override var rectType = RectType.ROUNDRECT

    //线的基类画笔
    val linePaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            color = Color.BLACK //(int)Color.rgb(26, 59, 105));
            style = Paint.Style.STROKE
            strokeWidth = 2f
        }
    }

    //背景画笔
    val backgroundPaint: Paint by lazy {
        Paint().apply {
            isAntiAlias = true
            style = Paint.Style.FILL
            color = Color.WHITE
            alpha = 220
        }
    }

    var borderColor:Int
        get() = strokeColor?.defaultColor?:Color.BLACK
        set(value) {
            strokeColor = ColorStateList.valueOf(value)
            linePaint.color = value
        }


    var backgroundColor:Int
        get() = fillColor?.defaultColor?:Color.WHITE
        set(value) {
            fillColor= ColorStateList.valueOf(value)
            backgroundPaint.color=value
        }

    var backgroundAlpha:Int
        get() = alpha
        set(value) {
            alpha=value
            backgroundPaint.alpha=value
        }

    init {
        paintStyle = Paint.Style.STROKE
        borderColor = Color.BLACK
        borderWidth = 2f
        backgroundColor = Color.WHITE
    }

    var isShowBorder = false

    var isShowBackground = false

    /**
     * 边框默认内边距
     * */
    var innerPadding = 5f

    val padding: RectanglePadding = RectanglePadding(innerRectangle)

    val horizontalPadding:Float get() = innerPadding * 2 + padding.horizontalPadding

    val verticalPadding:Float get() = innerPadding * 2 + padding.verticalPadding

    val left: Float get() = innerRectangle.left - padding.left - innerPadding
    val top: Float get() = innerRectangle.top - padding.top - innerPadding
    val right: Float get() = innerRectangle.right + padding.right + innerPadding
    val bottom: Float get() = innerRectangle.bottom - padding.bottom + innerPadding

    val realPadding: Padding get() = padding+innerPadding

    override fun contains(x: Float, y: Float): Boolean {
        val realPad = realPadding
        return realPad.contains(x, y, innerRectangle)
    }

    val borderRect:RectF get() = Padding.all(innerPadding).paddingRect(innerRectangle)

    val backgroundRect:RectF get() = innerRectangle.innerRect

    @SuppressLint("RestrictedApi")
    fun shadow(radius:Float, color:Int, verticalOffset:Int,mode: Int = SHADOW_COMPAT_MODE_ALWAYS){
        setShadowColor(color)
        shadowVerticalOffset = verticalOffset
        shadowCompatibilityMode = mode
        elevation = radius
    }


    override fun onSizeChanged(left: Float, top: Float, right: Float, bottom: Float) {
       setBounds(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
    }

    fun updateStyle(){

    }


}

fun Canvas.drawBorder(
    border: BorderDrawable
){
    val rect = border.borderRect
    drawBorder(border,rect.left,rect.top,rect.right,rect.bottom)
}

fun Canvas.drawBorder(
    border: BorderDrawable,
    left: Float, top: Float, right: Float, bottom: Float
) {
    if(border.isShowBackground || border.isShowBorder) {
        border.onSizeChanged(left, top, right, bottom)
        border.updateStyle()
        if(border.isShowBackground && border.isShowBorder) {
            border.paintStyle = Paint.Style.FILL_AND_STROKE
        }else {
            border.paintStyle = (border.isShowBorder).ifValue(Paint.Style.STROKE, Paint.Style.FILL)
        }
        border.draw(this)
    }
}

fun Canvas.drawBorderRect(border: BorderDrawable,
                          linePaint: Paint,
                          backgroundPaint:Paint,
                          lineSpacingStyle: LineSpacingStyle = LineSpacingStyle.Solid,
                          isShowBoxBorder: Boolean,
                          isShowBackground: Boolean
){
    val rect = border.borderRect
    val backgroundRect = border.backgroundRect
    when (border.rectType) {
        RectType.RECT -> {
            if (isShowBackground) drawRect(backgroundRect, backgroundPaint)
            if (isShowBoxBorder) drawRect(rect, linePaint)
        }
        RectType.ROUNDRECT -> {
            if (isShowBackground) drawRoundRect(
                backgroundRect, border.strokeWidth,
                border.strokeWidth, backgroundPaint
            )
            if (isShowBoxBorder) drawRoundRect(
                backgroundRect, border.strokeWidth,
                border.strokeWidth, linePaint
            )
        }
    }
}

fun Canvas.drawBorderCapRect(
    border: BorderDrawable, capHeight: Float,
    linePaint: Paint,
    backgroundPaint:Paint,
    showBoxBorder: Boolean, showBackground: Boolean
) {
    val rect = border.borderRect
    val path= Path()
    val centerX = rect.left + rect.width() * 0.5f
    val angleY = rect.bottom
    path.moveTo(rect.left, rect.bottom)
    path.lineTo(rect.left, rect.top)
    path.lineTo(rect.right, rect.top)
    path.lineTo(rect.right, rect.bottom)
    path.lineTo(centerX + capHeight, angleY)
    path.lineTo(centerX, angleY + capHeight)
    path.lineTo(centerX - capHeight, angleY)
    path.close()
    if (showBackground) drawPath(path, backgroundPaint)
    if (showBoxBorder) drawPath(path, linePaint)

}

fun Canvas.drawBorderCapRound(
    border: BorderDrawable, capHeight: Float,
    linePaint: Paint,
    backgroundPaint:Paint,
    showBoxBorder: Boolean, showBackground: Boolean
) {
    if (!showBackground) return
    val rect = border.borderRect
    val path= Path()

    val centerX = rect.left + rect.width() * 0.5f
    val AngleY = rect.bottom

    backgroundPaint.style = Paint.Style.FILL
    //mPaintBorderLine.setStyle(Style.STROKE);
    drawRoundRect(
        rect,
        border.strokeWidth,
        border.strokeWidth,
        backgroundPaint
    )
    val pHeight = CanvasExt.getPaintFontHeight(backgroundPaint)
    path.moveTo(centerX + capHeight, AngleY - pHeight)
    path.lineTo(centerX, AngleY + capHeight)
    path.lineTo(centerX - capHeight, AngleY - pHeight)
    path.close()
    drawPath(path, backgroundPaint)

    /*
    if(showBoxBorder)
    {
        mPath.moveTo(rect.left, rect.bottom);
        mPath.lineTo(rect.left, rect.top);
        mPath.lineTo(rect.right, rect.top);
        mPath.lineTo(rect.right, rect.bottom);
        mPath.lineTo( centerX + AngleH, AngleY);
        mPath.lineTo( centerX , AngleY + AngleH );
        mPath.lineTo( centerX - AngleH, AngleY);
        mPath.close();
        canvas.drawPath(mPath, mPaintBorderLine);
        mPath.reset();
    }
    */
}

fun Canvas.drawBorderRound(
    border: BorderDrawable, capHeight: Float,
    linePaint: Paint,
    backgroundPaint:Paint,
    showBoxBorder: Boolean, showBackground: Boolean
) {
    val rect = border.borderRect
    val backgroundRect = border.backgroundRect
    if (showBackground) drawRoundRect(
        backgroundRect,
        border.strokeWidth,
        border.strokeWidth,
        backgroundPaint
    )
    if (showBoxBorder) drawRoundRect(
        rect,
        border.strokeWidth,
        border.strokeWidth,
        linePaint
    )
}
